package org.lbm.flow.node;

import org.lbm.flow.agent.Agent;
import org.lbm.flow.context.FlowContext;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 基础节点抽象类
 * 提供节点的基础实现
 *
 * @author insist
 * @since 2025-08-01
 */
public abstract class BaseNode implements Node {

    protected final String id;
    protected final String name;
    protected final String type;
    protected final String description;
    protected final Map<String, Object> config;
    protected final List<String> predecessors;
    protected final List<String> successors;

    protected Agent agent;
    protected long timeout = 30000; // 默认30秒
    protected boolean enabled = true;

    protected BaseNode(String id, String name, String type, String description) {
        this.id = id;
        this.name = name;
        this.type = type;
        this.description = description;
        this.config = new HashMap<>();
        this.predecessors = new ArrayList<>();
        this.successors = new ArrayList<>();
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getType() {
        return type;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public Map<String, Object> getConfig() {
        return new HashMap<>(config);
    }

    @Override
    public List<String> getPredecessors() {
        return new ArrayList<>(predecessors);
    }

    @Override
    public List<String> getSuccessors() {
        return new ArrayList<>(successors);
    }

    @Override
    public void addPredecessor(String nodeId) {
        if (!predecessors.contains(nodeId)) {
            predecessors.add(nodeId);
        }
    }

    @Override
    public void addSuccessor(String nodeId) {
        if (!successors.contains(nodeId)) {
            successors.add(nodeId);
        }
    }

    @Override
    public boolean canExecute(FlowContext context) {
        if (!enabled) {
            return false;
        }

        // 检查前置节点是否都已完成
        for (String predecessorId : predecessors) {
            if (!isPredecessorCompleted(predecessorId, context)) {
                return false;
            }
        }

        return true;
    }

    @Override
    public Agent getAgent() {
        return agent;
    }

    @Override
    public void setAgent(Agent agent) {
        this.agent = agent;
    }

    @Override
    public long getTimeout() {
        return timeout;
    }

    @Override
    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }

    @Override
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    /**
     * 设置配置项
     */
    public void setConfig(String key, Object value) {
        config.put(key, value);
    }

    /**
     * 获取配置项
     */
    @SuppressWarnings("unchecked")
    public <T> T getConfig(String key) {
        return (T) config.get(key);
    }

    /**
     * 获取配置项，如果不存在则返回默认值
     */
    @SuppressWarnings("unchecked")
    public <T> T getConfig(String key, T defaultValue) {
        return (T) config.getOrDefault(key, defaultValue);
    }

    /**
     * 检查前置节点是否已完成
     * 子类可以重写此方法来实现自定义的前置节点检查逻辑
     */
    protected boolean isPredecessorCompleted(String predecessorId, FlowContext context) {
        // 默认实现：检查上下文中是否有前置节点的完成标记
        String completionKey = "node_completed_" + predecessorId;
        return context.hasVariable(completionKey);
    }

    /**
     * 标记节点完成
     */
    protected void markCompleted(FlowContext context) {
        context.setVariable("node_completed_" + id, true);
    }

    /**
     * 标记节点失败
     */
    protected void markFailed(FlowContext context) {
        context.setVariable("node_failed_" + id, true);
    }

    /**
     * 检查节点是否已完成
     */
    protected boolean isCompleted(FlowContext context) {
        return context.hasVariable("node_completed_" + id);
    }

    /**
     * 检查节点是否已失败
     */
    protected boolean isFailed(FlowContext context) {
        return context.hasVariable("node_failed_" + id);
    }

    @Override
    public String toString() {
        return String.format("BaseNode{id='%s', name='%s', type='%s', enabled=%s}",
                           id, name, type, enabled);
    }
}
